package com.coc.core.jwt;

import com.alibaba.fastjson.JSON;
import com.coc.core.redis.RedisOptCacheUtils;
import com.coc.core.security.service.UserDetailsServiceImpl;
import com.coc.core.utils.*;
import com.coc.entity.core.ResConfig;
import com.coc.entity.core.ResultCode;
import com.coc.entity.core.ResultTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author: songju
 * @date: 2020/10/15
 * @description: 确保在一次请求只通过一次filter，而不需要重复执行
 */

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter{
    @Autowired
    UserDetailsServiceImpl userDetailsService;
    @Autowired
    private ResConfig resConfig;
    @Autowired
    RedisOptCacheUtils redisUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取请求的ip地址
        String currentIp = AccessAddressUtil.getIpAddress(request);
        String authHeader = request.getHeader("Authorization");

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String authToken = authHeader.substring("Bearer ".length());

            String username = JwtTokenUtil.parseToken(authToken, "_secret");
            String ip = CollectionUtil.getMapValue(JwtTokenUtil.getClaims(authToken), "ip");
            //通过查询redis中的token值判断是否存在,是否登录
            boolean b = JudgeResUtil.JudgeIsMoblie(request);
            if (b){//手机端
                boolean b1 = redisUtils.hasKey("mobile_" + username);
                if (b1){
                    String redisToken = redisUtils.get("mobile_" + username).toString();
                    if (!redisToken.equals(authToken)){
                        response.getWriter().write(JSON.toJSONString(JSON.toJSONString(ResultTool.fail(ResultCode.USER_ACCOUNT_USE_BY_OTHERS))));
                        return;
                    }
                }else {
                    response.getWriter().write(JSON.toJSONString(JSON.toJSONString(ResultTool.fail(ResultCode.USER_ACCOUNT_USE_BY_OTHERS))));
                    return;
                }
            }else {
                boolean b2=redisUtils.hasKey("computer_"+username);
                if (b2){
                    String redisToken1 = redisUtils.get("computer_" + username).toString();
                    if (!redisToken1.equals(authToken)){
                        response.getWriter().write(JSON.toJSONString(ResultTool.fail(ResultCode.USER_ACCOUNT_USE_BY_OTHERS)));
                        return;
                    }
                }else {
                    response.getWriter().write(JSON.toJSONString(ResultTool.fail(ResultCode.USER_ACCOUNT_USE_BY_OTHERS)));
                    return;
                }
            }
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

                /*
                 * 加入对ip的验证
                 */
                if (!StringUtil.equals(ip, currentIp)) {//地址不正确,不许登录
                  response.getWriter().write(JSON.toJSONString(JSON.toJSONString(ResultTool.fail(ResultCode.IP_IS_CHANGE)), false));
                }
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                if (userDetails != null) {
                    UsernamePasswordAuthenticationToken authentication =
                            new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }

        filterChain.doFilter(request, response);
    }

}
